﻿using Furion.CMS.Core;
using Furion.CMS.Core.EventSource;
using Furion.CMS.Domain;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.EventBus;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Application
{
    /// <summary>
    /// 权限数据变更事件
    /// </summary>
    public class PermissionDataChangeEvent : IEventSubscriber, ISingleton
    {
        private readonly IDistributedCache<IEnumerable<string>> PermissionCache;

        /// <summary>
        /// 构造函数
        /// </summary>
        public PermissionDataChangeEvent(IDistributedCache<IEnumerable<string>> permissionCache)
        {
            PermissionCache = permissionCache;
        }

        /// <summary>
        /// 更新缓存项
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        [EventSubscribe(EventIdConsts.PermissionDataItemChange)]
        public async Task UpdateItem(EventHandlerExecutingContext context)
        {
            if (context.Source is OnPermissionDataItemChange dataChange && dataChange.Payload is IEnumerable<string> list)
            {
                var permissionCodes = (await PermissionCache.GetAsync(dataChange.Key))?.ToList();
                if (permissionCodes == null) return; //若权限代码为空则跳出更新
                if (dataChange.OperationType == CacheOperationType.Add)
                {
                    permissionCodes.AddRange(list);
                }
                else
                {
                    permissionCodes.RemoveAll(t => list.Contains(t));
                }
                // 更新缓存
                await PermissionCache.SetAsync(dataChange.Key, permissionCodes);
            }
        }

        /// <summary>
        /// 批量更新缓存项
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        [EventSubscribe(EventIdConsts.PermissionDataItemManyChange)]
        public async Task UpdateManyItem(EventHandlerExecutingContext context)
        {
            if (context.Source.Payload is IEnumerable<OnPermissionDataItemChange> list)
            {
                var items = list.GroupBy(g => g.Key).ToDictionary(k => k.Key, v => v.ToList());
                var keys = items.Keys;
                var historyCaches = await PermissionCache.GetManyAsync(keys);

                var updateCaches = new List<KeyValuePair<string, IEnumerable<string>>>();
                // 对数据进行分组处理
                for (int i = 0; i < historyCaches.Count(); i++)
                {
                    var hc = historyCaches[i];
                    // 如果不存在则需要创建
                    var permissionCodes = hc.Value?.ToList() ?? new List<string>();

                    var item = items.GetValueOrDefault(hc.Key);
                    var addList = item.Where(t => t.OperationType == CacheOperationType.Add)
                        .SelectMany(s => s.Payload as IEnumerable<string>).ToList();
                    var removeList = item.Where(t => t.OperationType == CacheOperationType.Remove)
                        .SelectMany(s => s.Payload as IEnumerable<string>).ToList();
                    // 更改缓存
                    permissionCodes.RemoveAll(t => removeList.Contains(t));
                    permissionCodes.AddRange(addList);
                    updateCaches.Add(KeyValuePair.Create<string, IEnumerable<string>>(hc.Key, permissionCodes));
                    // 清除缓存项
                    var clearList = item.Where(t => t.OperationType == CacheOperationType.Clear).Select(s => s.Key);
                    foreach(var key in clearList)
                    {
                        PermissionCache.Remove(key);
                    }
                }
                // 更新缓存
                await PermissionCache.SetManyAsync(updateCaches);
            }
        }
    }
}
